
typedef unsigned char  Byte;
typedef unsigned short Word;
typedef struct value_tag  Value;
typedef struct user_func_tag UserFunc;
typedef union entity_tag Entity;
typedef void (*SystemFunc) (int num, Value * base);
typedef enum {
    DATA_TYPE_NULL = 0,
    DATA_TYPE_BOOLEAN,
    DATA_TYPE_NUMBER,
    DATA_TYPE_STRING,
    DATA_TYPE_FUNC,
    DATA_TYPE_SYSTEM_FUNC,
    STACK_TAG,
} DataType; // 数据类型

typedef enum {
    VAR_NUMBER,
    VAR_STRING,
    VAR_FUNC
} VarType;

union entity_tag
{
    SystemFunc 	system_func; // 系统函数
    char    boolean;
    double  number;
    char    *string;
    //struct Map   *dicts;
    void    *null;
    UserFunc *user_func;
};

struct user_func_tag{
    Byte    *content;
    Word    content_length;
};

typedef enum{
    ATTR_VAR,
    ATTR_ARRAY,
    ATTR_ARRAY_DATA,
    ATTR_DICTS,
    ATTR_CONSTANT,
}Attribute;


struct value_tag
{
    char   *name;
    DataType  type;
    Attribute attr;
    Entity *entity;
    Word length;
    struct value_tag *array;
    //TODO 主要原因是获取数组层级后, 对于指针赋值时 会丢掉原来的地址链; 例如:
    // 一个f[2][3]和e[3]的数组, 当f[0]=e时, 这时栈 top-2 = top-1, 会直接 entity=entity
    //这时就会发生 f数组地址链丢失问题, 占时用一个备份指针记录上级地址, 后续有好方法再改进
    struct value_tag *backup_array;
};

// 字节码从1开始
// 因为calloc后,初始化内存数据0
typedef enum 
{ 
    PUSH_NULL=1,PUSH_CREATE_NUM, PUSH_CREATE_STR, PUSH_CREATE_FUNC, PUSH_CREATE_BOOL,
    PUSH_NUM, PUSH_STR, PUSH_FUNC, PUSH_BOOL,
    PUSH_ARRAY, PUSH_CREATE_ARRAY, PUSH_ARRAY_SET, PUSH_ARR_DEF,
    PUSH_NAME,PUSH_STRING,PUSH_NUMBER,
    PUSH_ASSIGN,
    PUSH_ADD, PUSH_SUB, PUSH_MUL, PUSH_DIV,
    PUSH_INSIDE_NAME, PUSH_FUNC_TAG, PUSH_RESET_ARGV, PUSH_FUNC_CALL, PUSH_DEF_FUNC, PUSH_REMOVE_STACK, PUSH_RET,
    RET_NULL, RET_ARR_NUM, RET_NUM, RET_ARR_STR, RET_STR, RET_ARR_BOOL, RET_BOOL,
    PUSH_COMPARISON_EQ, PUSH_COMPARISON_NEQ, PUSH_COMPARISON_GT, PUSH_COMPARISON_LT, PUSH_COMPARISON_GE, PUSH_COMPARISON_LE,
    PUSH_COMPARISON_AND, PUSH_COMPARISON_OR,
    PUSH_NOP,
    PUSH_IF_JMP,PUSH_JMP,PUSH_SUB_JMP,
    FILE_OVER
} OpCode;

typedef union
{
    unsigned char data[2];
    Word w;
} CodeWord;

typedef union
{
    unsigned char data[8];
    double n;
} CodeNumber;

#define LEX_DEBUG 0
#define CODE_DEBUG 0

#define get_index(inx , p)    { inx = *(Word *)p; p +=sizeof(Word);}
#define get_name_value(index)    { variable_node[index] }
#define get_constant_value(index)    { constant[index] }
#define put_stcak_cursor(cur, num)    { cur++; num++; }
#define pop_stcak_cursor(cur, num)    { cur--; num--; }

#define boolean_eq(left,right)    left->entity->boolean == right->entity->boolean 
#define boolean_neq(left,right)   left->entity->boolean != right->entity->boolean
#define boolean_gt(left,right)    left->entity->boolean >  right->entity->boolean
#define boolean_lt(left,right)    left->entity->boolean <  right->entity->boolean
#define boolean_ge(left,right)    left->entity->boolean >= right->entity->boolean
#define boolean_le(left,right)    left->entity->boolean <= right->entity->boolean

#define number_eq(left,right)    left->entity->number == right->entity->number
#define number_neq(left,right)   left->entity->number != right->entity->number
#define number_gt(left,right)    left->entity->number >  right->entity->number
#define number_lt(left,right)    left->entity->number <  right->entity->number
#define number_ge(left,right)    left->entity->number >= right->entity->number
#define number_le(left,right)    left->entity->number <= right->entity->number

#define string_eq(left,right)    left->entity->string == right->entity->string
#define string_neq(left,right)   left->entity->string != right->entity->string
#define string_gt(left,right)    left->entity->string >  right->entity->string
#define string_lt(left,right)    left->entity->string <  right->entity->string
#define string_ge(left,right)    left->entity->string >= right->entity->string
#define string_le(left,right)    left->entity->string <= right->entity->string

int initVM(Byte *bp, Word cur);
